#! /usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) Huoty, All rights reserved
# Author: Huoty <sudohuoty@gmail.com>
# CreateTime: 2018-01-19 22:56:17

import sys
import logging
from logging.handlers import RotatingFileHandler, SMTPHandler

from . import config
from .utils import Colorizing


defualt_logger = logging.getLogger("Tronitor")


info = defualt_logger.info
warn = defualt_logger.warning
warning = defualt_logger.warning
debug = defualt_logger.debug
error = defualt_logger.error
exception = defualt_logger.exception


class ColoredStreamHandler(logging.StreamHandler):
    """带色彩的流日志处理器"""

    _colors = {
        logging.DEBUG: "black",
        logging.INFO: "default",
        logging.WARNING: "yellow",
        logging.ERROR: "red",
        logging.CRITICAL: "on_red"
    }

    _c = Colorizing()

    def __init__(self, *args, **kwargs):
        super(ColoredStreamHandler, self).__init__(*args, **kwargs)

    @property
    def is_tty(self):
        isatty = getattr(self.stream, 'isatty', None)
        return isatty and isatty()

    def emit(self, record):
        try:
            message = self.format(record)
            stream = self.stream
            if not self.is_tty:
                stream.write(message)
            else:
                message = self._c(message, self._colors[record.levelno])
                stream.write(message)
            stream.write(getattr(self, 'terminator', '\n'))
            self.flush()
        except (KeyboardInterrupt, SystemExit):
            raise
        except Exception:
            self.handleError(record)


class TitledSMTPHandler(SMTPHandler):
    """可定制邮件主题 SMTP 日志处理器"""

    def __init__(self, *args, **kwargs):
        self.linefeed = "\r\n"
        super(TitledSMTPHandler, self).__init__(*args, **kwargs)

    def emit(self, record):
        # add extra record
        record.host = __import__("socket").gethostname()
        record.user = __import__("getpass").getuser()
        super(TitledSMTPHandler, self).emit(record)

    def getSubject(self, record):
        record = vars(record)
        record["message"] = record.get("message", '').strip().split('\n')[-1]
        return self.subject % record


class TronitorFilter(logging.Filter):
    """过滤非 Tronitor 的日志"""

    def filter(self, record):
        return record.name.startswith('Tronitor')


class FileLogFilter(logging.Filter):
    """日志文件过滤器"""

    def filter(self, record):
        return record.levelno >= logging.ERROR or record.name.startswith('Tronitor.Account')


def setup_logging(reset=False, enable_file_log=False, enable_extra_log=False,
                  enable_smtp_log=False):
    logger = logging.getLogger()

    if len(logger.handlers) > 0 and not reset:
        defualt_logger.debug("logging has been set up")
        return

    # empty handlers
    logger.handlers = []

    logger.setLevel(logging.DEBUG)

    # add stream log handler for info
    stream_handler = ColoredStreamHandler(sys.stdout)
    stream_handler.setLevel(logging.DEBUG)
    stream_handler.setFormatter(logging.Formatter(config.log_format))
    if not enable_extra_log:
        stream_handler.addFilter(TronitorFilter())
    logger.addHandler(stream_handler)

    # add rotating file log handler
    if enable_file_log and config.log_file_path:
        logfile = config.log_file_path
        logsize = config.log_file_maxsize or (5 * 1024 * 1024)
        backups = config.log_file_backups or 10
        file_handler = RotatingFileHandler(logfile, maxBytes=logsize, backupCount=backups)
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(logging.Formatter(config.log_format))
        if not enable_extra_log:
            file_handler.addFilter(TronitorFilter())
        logger.addHandler(file_handler)
        logger.debug("Added rotating file handler, logfile: %s, logsize: %s, backups: %s",
                     file_handler.baseFilename, file_handler.maxBytes, file_handler.backupCount)

    # add mail log handler for error
    if enable_smtp_log and config.email["toaddrs"]:
        smtp_handler = TitledSMTPHandler(
                mailhost=config.email["host"],
                fromaddr="TronitorErrorMonitor<{}>".format(config.email["addr"]),
                toaddrs=config.email["toaddrs"],
                subject="%(name)s Error: %(message)s",
                credentials=(config.email["addr"], config.email["passwd"]))
        smtp_handler.setLevel(logging.ERROR)
        smtp_handler.setFormatter(logging.Formatter(config.error_mail_format))
        logger.addHandler(smtp_handler)
